﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;

namespace UniFrame.Audio
{
    /// <summary>
    /// 音频类型
    /// </summary>
    public enum AudioType
    {
        /// <summary>
        /// 背景音乐
        /// </summary>
        BGM,
        /// <summary>
        /// UI音效
        /// </summary>
        UI,
        /// <summary>
        /// 特殊音效
        /// </summary>
        SFX
    }

    /// <summary>
    /// 音频管理器
    /// </summary>
    public class AudioManager
    {
        /// <summary>
        /// 音频混响器
        /// </summary>
        AudioMixer audioMixer;
        /// <summary>
        /// 背景音乐库
        /// </summary>
        Dictionary<UniRes, AudioSource> bgmDict;
        /// <summary>
        /// UI音频库
        /// </summary>
        Dictionary<UniRes, AudioSource> ufxDict;
        /// <summary>
        /// 特效音频库
        /// </summary>
        Dictionary<UniRes, AudioSource> sfxDict;

        /// <summary>
        /// 管理器吸附对象
        /// </summary>
        GameObject gameObject;
        /// <summary>
        /// 音频管理器
        /// </summary>
        /// <param name="attachObject">吸附对象</param>
        /// <param name="mixer">混响器</param>
        public AudioManager(GameObject attachObject, AudioMixer mixer = null)
        {
            audioMixer = mixer;
            gameObject = attachObject;
            bgmDict = new Dictionary<UniRes, AudioSource>();
            ufxDict = new Dictionary<UniRes, AudioSource>();
            sfxDict = new Dictionary<UniRes, AudioSource>();
        }
        /// <summary>
        /// 注册一个音频信息
        /// </summary>
        /// <param name="uniRes"></param>
        /// <param name="audioType"></param>
        /// <param name="mixerSubPath"></param>
        public void Register(UniRes uniRes, AudioType audioType = AudioType.UI, string mixerSubPath = null)
        {
            switch (audioType)
            {
                case AudioType.BGM:
                    if (bgmDict.ContainsKey(uniRes))
                        return;
                    break;
                case AudioType.UI:
                    if (ufxDict.ContainsKey(uniRes))
                        return;
                    break;
                case AudioType.SFX:
                    if (sfxDict.ContainsKey(uniRes))
                        return;
                    break;
            }
            AudioSource auSrc = gameObject.AddComponent<AudioSource>();
            auSrc.clip = Resources.Load<AudioClip>(uniRes.Path);
            auSrc.outputAudioMixerGroup = audioMixer?.FindMatchingGroups(mixerSubPath)[0];
            auSrc.loop = audioType == AudioType.BGM;
            auSrc.playOnAwake = false;

            switch (audioType)
            {
                case AudioType.BGM:
                    bgmDict.Add(uniRes, auSrc);
                    break;
                case AudioType.UI:
                    ufxDict.Add(uniRes, auSrc);
                    break;
                case AudioType.SFX:
                    sfxDict.Add(uniRes, auSrc);
                    break;
            }
        }
        /// <summary>
        /// 播放一个音频
        /// </summary>
        /// <param name="uniRes"></param>
        /// <param name="audioType"></param>
        public void Play(UniRes uniRes, AudioType audioType = AudioType.UI)
        {
            switch (audioType)
            {
                case AudioType.BGM:
                    if (!bgmDict.ContainsKey(uniRes))
                        return;
                    foreach (var item in bgmDict)
                        if (item.Key != uniRes)
                            item.Value.Stop();
                    bgmDict[uniRes].Play();
                    break;
                case AudioType.UI:
                    if (!ufxDict.ContainsKey(uniRes))
                        return;
                    ufxDict[uniRes].Play();
                    break;
                case AudioType.SFX:
                    if (!sfxDict.ContainsKey(uniRes))
                        return;
                    sfxDict[uniRes].Play();
                    break;
            }
        }
        /// <summary>
        /// 播放一个音频
        /// </summary>
        /// <param name="name"></param>
        /// <param name="audioType"></param>
        public void Play(string name,AudioType audioType = AudioType.UI)
        {
            switch (audioType)
            {
                case AudioType.BGM:
                    foreach (var item in bgmDict)
                    {
                        if (item.Key.Name == name)
                            item.Value.Play();
                        else
                            item.Value.Stop();
                    }
                    break;
                case AudioType.UI:
                    foreach (var item in ufxDict)
                    {
                        if (item.Key.Name == name)
                        {
                            item.Value.Play();
                            return;
                        }
                    }
                    break;
                case AudioType.SFX:
                    foreach (var item in sfxDict)
                    {
                        if (item.Key.Name == name)
                        {
                            item.Value.Play();
                            return;
                        }
                    }
                    break;
            }
        }
        /// <summary>
        /// 停止播放一个音频
        /// </summary>
        /// <param name="uniRes"></param>
        /// <param name="audioType"></param>
        public void Stop(UniRes uniRes,AudioType audioType)
        {
            switch (audioType)
            {
                case AudioType.BGM:
                    if (!bgmDict.ContainsKey(uniRes))
                        return;
                    bgmDict[uniRes].Stop();
                    break;
                case AudioType.UI:
                    if (!ufxDict.ContainsKey(uniRes))
                        return;
                    ufxDict[uniRes].Stop();
                    break;
                case AudioType.SFX:
                    if (!sfxDict.ContainsKey(uniRes))
                        return;
                    sfxDict[uniRes].Stop();
                    break;
            }
        }
        /// <summary>
        /// 停止播放一个音频
        /// </summary>
        /// <param name="name"></param>
        /// <param name="audioType"></param>
        public void Stop(string name, AudioType audioType = AudioType.UI)
        {
            switch (audioType)
            {
                case AudioType.BGM:
                    foreach (var item in bgmDict)
                    {
                        if (item.Key.Name == name)
                        {
                            item.Value.Stop();
                            return;
                        }
                    }
                    break;
                case AudioType.UI:
                    foreach (var item in ufxDict)
                    {
                        if (item.Key.Name == name)
                        {
                            item.Value.Stop();
                            return;
                        }
                    }
                    break;
                case AudioType.SFX:
                    foreach (var item in sfxDict)
                    {
                        if (item.Key.Name == name)
                        {
                            item.Value.Stop();
                            return;
                        }
                    }
                    break;
            }
        }
        /// <summary>
        /// 获取音源组件
        /// </summary>
        /// <param name="uniRes"></param>
        /// <param name="audioType"></param>
        /// <returns></returns>
        public AudioSource GetAudioSource(UniRes uniRes,AudioType audioType = AudioType.UI)
        {
            AudioSource audioSource = null;
            switch (audioType)
            {
                case AudioType.BGM:
                    if (bgmDict.ContainsKey(uniRes))
                        audioSource = bgmDict[uniRes];
                    break;
                case AudioType.UI:
                    if (ufxDict.ContainsKey(uniRes))
                        audioSource = ufxDict[uniRes];
                    break;
                case AudioType.SFX:
                    if (sfxDict.ContainsKey(uniRes))
                        audioSource = sfxDict[uniRes];
                    break;
            }
            return audioSource;
        }
        /// <summary>
        /// 获取音源组件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="audioType"></param>
        /// <returns></returns>
        public AudioSource GetAudioSource(string name, AudioType audioType = AudioType.UI)
        {
            AudioSource audioSource = null;
            switch (audioType)
            {
                case AudioType.BGM:
                    foreach (var item in bgmDict)
                    {
                        if (item.Key.Name == name)
                        {
                            audioSource = item.Value;
                            break;
                        }
                    }
                    break;
                case AudioType.UI:
                    foreach (var item in ufxDict)
                    {
                        if (item.Key.Name == name)
                        {
                            audioSource = item.Value;
                            break;
                        }
                    }
                    break;
                case AudioType.SFX:
                    foreach (var item in sfxDict)
                    {
                        if (item.Key.Name == name)
                        {
                            audioSource = item.Value;
                            break;
                        }
                    }
                    break;
            }
            return audioSource;
        }
        /// <summary>
        /// 获取混响器
        /// </summary>
        /// <returns></returns>
        public AudioMixer GetAudioMixer() { return audioMixer; }
        /// <summary>
        /// 设置混响器暴露参数
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool SetFloat(string name,float value)
        {
            if(audioMixer != null)
                return audioMixer.SetFloat(name, value);
            return false;
        }
    }
}
